// #include <GL/glew.h>  
// #include <GLFW/glfw3.h>
#include <iostream>

#include "vortex/graphics/renderer/sprite_renderer.h"
#include "vortex/graphics/renderer/bfont_renderer.h"
#include "vortex/graphics/renderer/mesh_renderer1.h"
#include "vortex/graphics/renderer/mesh_renderer.h"
#include "vortex/graphics/renderer/cubemap_renderer.h"

#include "vortex/ui/uilayer.h"
#include "vortex/graphics/projection.h"
#include "vortex/core/window.h"
#include "vortex/core/asset.h"
#include "vortex/core/rng.h"
#include "vortex/core/timer.h"

#include <glm/gtc/matrix_transform.hpp>

int main() 
{
    vortex::WindowProps props = 
    {
        1280, 960, "OpenGL"
    };
    std::shared_ptr<vortex::Window> window = std::make_shared<vortex::Window>(props);

    std::shared_ptr<vortex::MeshRenderer1> mesh_renderer1 = std::make_shared<vortex::MeshRenderer1>();
    std::shared_ptr<vortex::CubemapRenderer> skybox_renderer = std::make_shared<vortex::CubemapRenderer>();
    std::shared_ptr<vortex::MeshRenderer> mesh_renderer = std::make_shared<vortex::MeshRenderer>();

    std::shared_ptr<vortex::UILayer> ui_renderer = std::make_shared<vortex::UILayer>();
    auto windowHandle = window->GetHandle();
    ui_renderer->Initialize(windowHandle);

    // render scene
    vortex::Environment3D env3d;
    env3d.camera = std::make_shared<vortex::Camera3D>();
    env3d.window_width = window->GetWidth();
    env3d.window_height = window->GetHeight();

    float camera_yaw = 0.0f;
    float camera_pitch = 0.0f;
    env3d.camera->moveTo(0.0f, 1.0f, -8.0f);
    float box_offset = 0.0f;

    // font and text
    std::string font_path = vortex::get_asset_path("fonts/OpenSans-Regular.ttf");
    std::string text("Hello");

    // mesh
    std::string mesh_path = vortex::get_asset_path("mesh/suzanne.obj");
    vortex::Mesh1 mesh(mesh_path);
    std::shared_ptr<vortex::Mesh> plane = vortex::Mesh::plane();
    std::shared_ptr<vortex::Mesh> box = vortex::Mesh::box();

    // cubemap
    std::vector<std::string> skybox_textures = {
        vortex::get_asset_path("textures/skybox/+x.png"),
        vortex::get_asset_path("textures/skybox/-x.png"),
        vortex::get_asset_path("textures/skybox/+y.png"),
        vortex::get_asset_path("textures/skybox/-y.png"),
        vortex::get_asset_path("textures/skybox/+z.png"),
        vortex::get_asset_path("textures/skybox/-z.png"),
    };
    vortex::Cubemap cm;
    cm.Load(skybox_textures);

    vortex::Timer timer;

    while (!window->Closed()) 
    {
#if OPENGL_API
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        // glClearDepth(-1000.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#endif
        window->ProcessEvents();

        env3d.camera->SetYaw(camera_yaw);
        env3d.camera->SetPitch(camera_pitch);

#if 1
        skybox_renderer->Begin(env3d);
        skybox_renderer->Draw(cm);
        skybox_renderer->End();
#endif

#if 0
        // mesh rendering
        mesh_renderer1->Begin(env3d);
        mesh_renderer1->Draw(mesh);
        mesh_renderer1->End();
#endif

#if 1
        glm::mat4 t1 = glm::mat4(1.0f);
        t1 = glm::translate(t1, glm::vec3(box_offset, 0.0f, 0.0));

        mesh_renderer->Begin(env3d);
        mesh_renderer->Draw(*box, t1);
        mesh_renderer->Draw(*plane);
        mesh_renderer->End();
#endif

#if 1
        // ui is rendered last
        ui_renderer->BeginFrame();
        // ui_renderer->ShowDemoWindow();
        ui_renderer->BeginWindow("camera");
        ImGui::SliderFloat("yaw", &camera_yaw, -90.0f, 90.0f);
        ImGui::SliderFloat("pitch", &camera_pitch, -90.0f, 90.0f);
        ImGui::SliderFloat("offset", &box_offset, -10.0f, 10.0f);
        ui_renderer->EndWindow();
        ui_renderer->EndFrame();
#endif

        window->Update();
    }

    // glfwTerminate();
    return 0;
}
